package com.zy.je.common.mybatis.ext.activerecord;

import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.core.enums.SqlMethod;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
import com.zy.je.common.core.constant.QueryType;
import com.zy.je.common.core.constant.StringPool;
import com.zy.je.common.core.model.QueryMap;
import com.zy.je.common.core.model.ResultMap;
import com.zy.je.common.core.utils.CheckUtil;
import com.zy.je.common.mybatis.ext.inf.IBaseEntity;
import com.zy.je.common.mybatis.ext.inf.IIdentity;
import com.zy.je.common.mybatis.ext.model.IPageQuery;
import com.zy.je.common.mybatis.ext.util.WrapperUtil;
import io.swagger.annotations.ApiParam;
import lombok.*;
import lombok.experimental.SuperBuilder;
import org.apache.ibatis.session.SqlSession;

import java.io.Serializable;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author zy
 */
@NoArgsConstructor
@AllArgsConstructor
//@SuperBuilder
@Data
@EqualsAndHashCode(callSuper = true)
public abstract class BaseArModel<I extends Serializable, T extends BaseArModel<?,?>> extends Model<T>
        implements IIdentity<I>, IBaseEntity<I>
        , IPageQuery, QueryMap, ResultMap {
    /**
     * 主键ID
     */
    @TableId(value = "id", type = IdType.ASSIGN_ID)
    private I id;

    /**
     * 创建者
     */
    @TableField(fill = FieldFill.INSERT)
    private String createBy;

    /**
     * 创建时间
     */
    @TableField(fill = FieldFill.INSERT)
    private Date createTime;

    /**
     * 创建操作员
     */
    @TableField(fill = FieldFill.INSERT)
    private String createUsername;

    /**
     * 更新者
     */
    @TableField(fill = FieldFill.UPDATE)
    private String updateBy;

    /**
     * 更新时间
     */
    @TableField(fill = FieldFill.UPDATE)
    private Date updateTime;

    /**
     * 更新操作员
     */
    @TableField(fill = FieldFill.UPDATE)
    private String updateUsername;

    /**
     * 排序字段
     */
//    @ApiModelProperty(value = "排序字段")
    @TableField(exist = false)
    private String _orderBy;

    /**
     * 页码
     */
//    @ApiModelProperty(value = "页码")
    @TableField(exist = false)
    private Integer pageNo;
    /**
     * 每页数量
     */
//    @ApiModelProperty(value = "每页数量")
    @TableField(exist = false)
    private Integer pageSize;

    /**
     * 查询条件增强
     */
//    @ApiModelProperty(value = "查询条件增强")
    @TableField(exist = false)
    protected Map<String, String> _q;
    /**
     * 扩展的返回结果--用于保存字段的翻译
     */
    @ApiParam(hidden = true)
    @TableField(exist = false)
    protected Map<String, Object> _r;

    @Override
    public Map<String, Object> buildR() {
        if (null == this._r) {
            this._r = new HashMap<>();
        }
        return this._r;
    }

    @Override
    public Map<String, String> buildQ() {
        if (null == this._q) {
            this._q = new HashMap<>();
        }
        return this._q;
    }

    @Override
    public <T> Page<T> buildPage() {
        int tmpPageNo = pageNo == null ? 1 : pageNo;
        int tmpPageSize = pageSize == null ? 10 : pageSize;
        Page<T> page = new Page<>((long) tmpPageNo, (long) tmpPageSize);
        //处理排序
        List<OrderItem> orders = WrapperUtil.fmtOrderBy2OrderItems(buildOrderBy());
        if (!CheckUtil.isBlank(orders)) {
            page.setOrders(orders);
        }
        return page;
    }


    @Override
    public String buildOrderBy() {
        String orderByKey = StringPool.UNDERSCORE + QueryType.ORDER_BY.getValue();
        for (Map.Entry<String, String> entry : buildQ().entrySet()) {
            if (entry.getKey().endsWith(orderByKey)) {
                if (!CheckUtil.isBlank(entry.getValue())) {
                    return WrapperUtil.fmtOrderBy(entry.getValue());
                }
            }
        }
        return WrapperUtil.fmtOrderBy(_orderBy);
    }

    // builder模式 ---------------------------------------------------------

    protected BaseArModel(final BaseArModelBuilder<I, T, ?, ?> b) {
        super();
        this.id = b.id;
        this.createBy = b.createBy;
        this.createTime = b.createTime;
        this.createUsername = b.createUsername;
        this.updateBy = b.updateBy;
        this.updateTime = b.updateTime;
        this.updateUsername = b.updateUsername;
        this._orderBy = b._orderBy;
        this.pageNo = b.pageNo;
        this.pageSize = b.pageSize;
        this._q = b._q;
        this._r = b._r;
    }

    public abstract static class BaseArModelBuilder<I extends Serializable, T extends BaseArModel<?, ?>, C extends BaseArModel<I, T>, B extends BaseArModelBuilder<I, T, C, B>> extends ModelBuilder<T, C, B> {
        private I id;
        private String createBy;
        private Date createTime;
        private String createUsername;
        private String updateBy;
        private Date updateTime;
        private String updateUsername;
        private String _orderBy;
        private Integer pageNo;
        private Integer pageSize;
        private Map<String, String> _q;
        private Map<String, Object> _r;

        public BaseArModelBuilder() {
        }

        public B id(final I id) {
            this.id = id;
            return this.self();
        }

        public B createBy(final String createBy) {
            this.createBy = createBy;
            return this.self();
        }

        public B createTime(final Date createTime) {
            this.createTime = createTime;
            return this.self();
        }

        public B createUsername(final String createUsername) {
            this.createUsername = createUsername;
            return this.self();
        }

        public B updateBy(final String updateBy) {
            this.updateBy = updateBy;
            return this.self();
        }

        public B updateTime(final Date updateTime) {
            this.updateTime = updateTime;
            return this.self();
        }

        public B updateUsername(final String updateUsername) {
            this.updateUsername = updateUsername;
            return this.self();
        }

        public B _orderBy(final String _orderBy) {
            this._orderBy = _orderBy;
            return this.self();
        }

        public B pageNo(final Integer pageNo) {
            this.pageNo = pageNo;
            return this.self();
        }

        public B pageSize(final Integer pageSize) {
            this.pageSize = pageSize;
            return this.self();
        }

        public B _q(final Map<String, String> _q) {
            this._q = _q;
            return this.self();
        }

        public B _r(final Map<String, Object> _r) {
            this._r = _r;
            return this.self();
        }

        @Override
        protected abstract B self();

        @Override
        public abstract C build();

        @Override
        public String toString() {
            String var10000 = super.toString();
            return "BaseArModel.BaseArModelBuilder(super=" + var10000 + ", id=" + String.valueOf(this.id) + ", createBy=" + this.createBy + ", createTime=" + String.valueOf(this.createTime) + ", createUsername=" + this.createUsername + ", updateBy=" + this.updateBy + ", updateTime=" + String.valueOf(this.updateTime) + ", updateUsername=" + this.updateUsername + ", _orderBy=" + this._orderBy + ", pageNo=" + this.pageNo + ", pageSize=" + this.pageSize + ", _q=" + String.valueOf(this._q) + ", _r=" + String.valueOf(this._r) + ")";
        }
    }
    public abstract static class ModelBuilder<T extends Model<?>, C extends Model<T>, B extends ModelBuilder<T, C, B>> {
        public ModelBuilder() {
        }

        protected abstract B self();

        public abstract C build();

        @Override
        public String toString() {
            return "Model.ModelBuilder()";
        }
    }
}